home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / workbnch / launch.1 < prev    next >
Text File  |  1989-01-31  |  11KB  |  458 lines

  1. Path: xanth!ames!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i002:  launch - start workbench tasks from cli
  5. Message-ID: <11476@swan.ulowell.edu>
  6. Date: 31 Jan 89 05:00:17 GMT
  7. Sender: news@swan.ulowell.edu
  8. Organization: University of Lowell, Computer Science Dept.
  9. Lines: 446
  10. Approved: page@swan.ulowell.edu
  11.  
  12. Submitted-by: peter@sugar.uu.net (Peter da Silva)
  13. Posting-number: Volume 89, Issue 2
  14. Archive-name: workbench/launch.1
  15.  
  16. This is an example of how you run a workbench application. As you can
  17. see, it's pretty complex... even with the stuff encapsulated like
  18. this. However, once you get it working it works just fine... unlike
  19. the CLI. Just ask anyone who's tried to run a program under the CLI
  20. from, say, runback.
  21.  
  22. [Originally posted Sept. 88 in alt.sources.amiga.  ..Bob]
  23.  
  24. #    This is a shell archive.
  25. #    Remove everything above and including the cut line.
  26. #    Then run the rest of the file through sh.
  27. #----cut here-----cut here-----cut here-----cut here----#
  28. #!/bin/sh
  29. # shar:    Shell Archiver
  30. #    Run the following text with /bin/sh to create:
  31. #    Makefile
  32. #    launch.c
  33. #    launch.doc
  34. #    util.c
  35. #    wbcleanup.c
  36. #    wbfree.c
  37. #    wblaunch.c
  38. # This archive created: Mon Jan 30 15:27:38 1989
  39. cat << \SHAR_EOF > Makefile
  40. TEXT= launch.doc launch.c wblaunch.c wbfree.c wbcleanup.c util.c Makefile
  41. BIN=  launch wbcleanup
  42. LOBJS= launch.o wblaunch.o wbfree.o util.o
  43. WOBJS= wbcleanup.o wbfree.o
  44.  
  45. .SUFFIXES: .c .o .h .x
  46.  
  47. .c.o:
  48.     -delete $*.o
  49.     cc +P -B -DAMIGA $*.c
  50.  
  51. all: $(BIN)
  52.  
  53. launch: $(LOBJS)
  54.     -delete launch
  55.     ln -o launch $(LOBJS) -lcl32
  56.  
  57. wbcleanup: $(WOBJS)
  58.     -delete wbcleanup
  59.     ln -o wbcleanup $(WOBJS) -lcl32
  60.  
  61. launch.arc: $(TEXT) $(BIN)
  62.     arc a launch  $(TEXT) $(BIN)
  63.  
  64. launch.shar: $(TEXT)
  65.     shar >launch.shar $(TEXT)
  66.  
  67. clean:
  68.     -delete #?.o #?.bak #?.arc #?.shar launch wbcleanup
  69. SHAR_EOF
  70. cat << \SHAR_EOF > launch.c
  71. #include <libraries/dosextens.h>
  72. #include <exec/ports.h>
  73. #include <workbench/startup.h>
  74. #include <workbench/workbench.h>
  75. #include <stdio.h>
  76.  
  77. struct MsgPort *FindPort(), *CreatePort();
  78. struct WBStartup *Launch(), *GetMsg();
  79. struct Process *FindTask();
  80.  
  81. main(ac, av)
  82. int ac;
  83. char **av;
  84. {
  85.     struct MsgPort *rport;
  86.     struct Process *me;
  87.     struct CommandLineInterface *cli;
  88.     struct WBStartup *startup;
  89.  
  90.     long stack;
  91.     int pri;
  92.     char *win;
  93.     int wait;
  94.     int got_arg;
  95.  
  96.     stack = 0;
  97.     pri = 0;
  98.     win = 0;
  99.     wait = 0;
  100.  
  101.     if(ac < 2 || strcmp(av[1], "?") == 0) {
  102.         fprintf(stderr,
  103. "launch [stack nnnn] [window name] [priority PRI] [wait] program [arguments]\n"
  104.             );
  105.         exit((ac<2)?5:0);
  106.     }
  107.     got_arg = 1;
  108.     while(got_arg == 1 && ac >= 3) {
  109.         got_arg = 0;
  110.         if(dictcmp(av[1], "window") == 0) {
  111.             win = av[2];
  112.             av += 2;
  113.             ac -= 2;
  114.             got_arg = 1;
  115.         } else if(dictcmp(av[1], "stack") == 0) {
  116.             stack = atol(av[2]);
  117.             av += 2;
  118.             ac -= 2;
  119.             got_arg = 1;
  120.         } else if(dictcmp(av[1], "priority") == 0) {
  121.             pri = atoi(av[2]);
  122.             av += 2;
  123.             ac -= 2;
  124.             got_arg = 1;
  125.         } else if(dictcmp(av[1], "wait") == 0) {
  126.             wait = 1;
  127.             av ++;
  128.             ac --;
  129.             got_arg = 1;
  130.         }
  131.     }
  132.  
  133.     if(wait == 0) {
  134.         if(!(rport = FindPort("Workbench.Cleanup"))) {
  135.             fprintf(stderr, "Could not find Workbench.Cleanup port.\n");
  136.             fprintf(stderr, "Are you sure you ran wbcleanup?\n");
  137.             exit(20);
  138.         }
  139.     } else {
  140.         if(!(rport = CreatePort(0, 0))) {
  141.             printf("Can't create reply port.\n");
  142.             exit(20);
  143.         }
  144.     }
  145.     if(stack == 0) {
  146.         me = FindTask(0);
  147.         if(me->pr_CLI) {
  148.             cli = (struct CommandLineInterface *)(me->pr_CLI<<2);
  149.             stack = cli->cli_DefaultStack<<2; /* DefaultStack is in Longwords */
  150.         } else
  151.             stack = me->pr_StackSize;
  152.     }
  153.     if(!Launch(rport, av[1], &av[1], ac-1, pri, win, stack)) {
  154.         fprintf(stderr, "Could not launch %s error %d\n", av[1], IoErr());
  155.         exit(20);
  156.     }
  157.     if(wait != 0) {
  158.         WaitPort(rport);
  159.         startup = GetMsg(rport);
  160.         FreeStartup(startup);
  161.         DeletePort(rport);
  162.     }
  163.     exit(0);
  164. }
  165. SHAR_EOF
  166. cat << \SHAR_EOF > launch.doc
  167. LAUNCH -- start a workbench application from the CLI.
  168.  
  169. This is an example of how you run a workbench application. As you can see,
  170. it's pretty complex... even with the stuff encapsulated like this. However,
  171. once you get it working it works just fine... unlike the CLI. Just ask anyone
  172. who's tried to run a program under the CLI from, say, runback.
  173.  
  174. Usage:
  175.     run wbcleanup (only once, in your CLI)
  176.     launch [options] program [filename]...
  177.  
  178.     Loads and executes program in a workbench environment, then returns to
  179.     the CLI.
  180.  
  181. Options:
  182.     stack nnnn
  183.         Specifies initial stack for the program.
  184.     priority pppp
  185.         Specifies initial priority for the program.
  186.     window wwww
  187.         Specifies TOOLWINDOW for the program.
  188.     wait
  189.         Wait for reply, rather than passing it off to wbcleanup.
  190.  
  191. wblaunch.c:
  192.     message = Launch(port, program, argv, argc, pri, win, stack);
  193.  
  194.     Launch loads and executes program in a workbench environment. The
  195.     specified port is where the startup message will be returned. The
  196.     arguments will be passed to the program, workbench-style (directory
  197.     lock and filename). The first argument should be the same as the
  198.     program, but it's possible to spawn a program in an illicit way. If
  199.     you don't want to specify a window, use NULL. You need to specify a
  200.     stack.
  201.  
  202.     If you don't want to specify a port, run wbcleanup and use the public
  203.     message port "Workbench.Cleanup".
  204.  
  205.     You really don't need to do anything with the message when it's
  206.     returned from Launch, but it's a convenient non-zero value to indicate
  207.     success.
  208.  
  209. wbfree.c:
  210.     FreeStartup(message);
  211.  
  212.     FreeStartup takes a startup message created by Launch and releases all
  213.     the public memory, removes the lock, and so on. It should be called
  214.     after the startup message is returned.
  215.  
  216. launch.c:
  217.     This contains the mainline for the 'launch' program. Most of it is
  218.     arg parsing.
  219.  
  220. wbcleanup.c:
  221.     This contains the mainline for the 'wbcleanup' program.
  222.  
  223. util.c:
  224.     dictcmp(s1, s2);
  225.  
  226.     An analog to strcmp, but ignores case differences in words. Not a full
  227.     dictionary comparison, since it doesn't sort numbers by their spelling.
  228. SHAR_EOF
  229. cat << \SHAR_EOF > util.c
  230. #include <ctype.h>
  231.  
  232. dictcmp(s1, s2)
  233. char *s1;
  234. char *s2;
  235. {
  236.     while(*s1 && *s2) {
  237.         char c1 = *s1;
  238.         char c2 = *s2;
  239.         if(isupper(c1)) c1 = tolower(c1);
  240.         if(isupper(c2)) c2 = tolower(c2);
  241.         if(c1 != c2)
  242.             return c1-c2;
  243.         s1++;
  244.         s2++;
  245.     }
  246.     return *s1 - *s2;
  247. }
  248. SHAR_EOF
  249. cat << \SHAR_EOF > wbcleanup.c
  250. #include <exec/memory.h>
  251. #include <workbench/startup.h>
  252. #include <workbench/workbench.h>
  253.  
  254. struct MsgPort *rport, *CreatePort();
  255. struct WBStartup *startup, *GetMsg();
  256.  
  257. main()
  258. {
  259.     if(!(rport = CreatePort("Workbench.Cleanup", 0))) {
  260.         printf("Can't create Workbench.Cleanup port.\n");
  261.         exit(20);
  262.     }
  263.     while(1) {
  264.         WaitPort(rport);
  265.         startup = GetMsg(rport);
  266.         FreeStartup(startup);
  267.     }
  268. }
  269. SHAR_EOF
  270. cat << \SHAR_EOF > wbfree.c
  271. #include <exec/memory.h>
  272. #include <workbench/startup.h>
  273. #include <workbench/workbench.h>
  274.  
  275. FreeStartup(msg)
  276. struct WBStartup *msg;
  277. {
  278.     /* Free the files. Assumes they have been allocated via Launch, so
  279.      * they're just AllocMemmed. UnLock all the Locks, and Free the
  280.      * names.
  281.      */
  282.     if(msg->sm_ArgList) {
  283.         int i;
  284.         for(i = 0; i < msg->sm_NumArgs; i++) {
  285.             if(msg->sm_ArgList[i].wa_Lock)
  286.                 UnLock(msg->sm_ArgList[i].wa_Lock);
  287.             if(msg->sm_ArgList[i].wa_Name)
  288.                 FreeMem(msg->sm_ArgList[i].wa_Name,
  289.                     strlen(msg->sm_ArgList[i].wa_Name)+1);
  290.         }
  291.         FreeMem(msg->sm_ArgList,
  292.             sizeof(struct WBArg) * msg->sm_NumArgs);
  293.     }
  294.  
  295.     /* Here goes the program...
  296.      */
  297.     if(msg->sm_Segment)
  298.         UnLoadSeg(msg->sm_Segment);
  299.  
  300.     /* And the name of the window. Again, assuming it's allocated by
  301.      * Launch, so it just fits in its AllocMemmed buffer.
  302.      */
  303.     if(msg->sm_ToolWindow)
  304.         FreeMem(msg->sm_ToolWindow,
  305.             strlen(msg->sm_ToolWindow)+1);
  306.  
  307.     /* And finally the message itself */
  308.     FreeMem(msg, sizeof(struct WBStartup));
  309. }
  310. SHAR_EOF
  311. cat << \SHAR_EOF > wblaunch.c
  312. #include <exec/memory.h>
  313. #include <workbench/startup.h>
  314. #include <workbench/workbench.h>
  315.  
  316. UBYTE *AllocMem();
  317. BPTR LoadSeg();
  318. struct MsgPort *CreateProc();
  319.  
  320. /* Launch(rport, name, argv, argc, pri, win, stack) -- launch a program.
  321.  *
  322.  * Launch builds a startup message, loads a program, and launches it.
  323.  *
  324.  * Arguments:
  325.  *    rport -- reply port to receive startup message back when the program
  326.  *             finishes.
  327.  *    name  -- File name for the program to load.
  328.  *    argv  -- list of filenames to pass to loaded program.
  329.  *    argc  -- length of argument list.
  330.  *    pri   -- priority of the new process.
  331.  *    win   -- ToolWindow for the new process, or NULL.
  332.  *    stack -- Stack size for the new process.
  333.  *
  334.  * argv[0] should be the same as the program. pri should normally be 0.
  335.  * stack should normally be at least 4K.
  336.  */
  337. struct WBStartup *
  338. Launch(rport, name, argv, argc, pri, win, stack)
  339. struct MsgPort *rport;
  340. char *name;
  341. char **argv;
  342. int argc;
  343. long pri;
  344. char *win;
  345. ULONG stack;
  346. {
  347.     ULONG flock;
  348.     struct WBStartup *msg;
  349.     char *s, *namep;
  350.     int i;
  351.  
  352.     if(!rport)
  353.         return 0;
  354.  
  355.     /* Get some space to work in -- the startup message */
  356.     msg = (struct WBStartup *)
  357.         AllocMem(sizeof(struct WBStartup), MEMF_PUBLIC|MEMF_CLEAR);
  358.     if(!msg)
  359.         return 0;
  360.  
  361.     /* Now load the program */
  362.     msg->sm_Segment = LoadSeg(name);
  363.     if(!msg->sm_Segment) {
  364.         FreeStartup(msg);
  365.         return 0;
  366.     }
  367.  
  368.     /* Allocate and link in the window description */
  369.     if(win) {
  370.         msg->sm_ToolWindow = (char *)AllocMem(strlen(win)+1, MEMF_PUBLIC);
  371.         if(!msg->sm_ToolWindow) {
  372.             FreeStartup(msg);
  373.             return 0;
  374.         }
  375.         strcpy(msg->sm_ToolWindow, win);
  376.     } else
  377.         msg->sm_ToolWindow = 0;
  378.  
  379.     /* Allocate the arg list */
  380.     msg->sm_ArgList = (struct WBArg *)
  381.         AllocMem(sizeof(struct WBArg) * argc, MEMF_PUBLIC | MEMF_CLEAR);
  382.     if(!msg->sm_ArgList) {
  383.         FreeStartup(msg);
  384.         return 0;
  385.     }
  386.  
  387.     /* Empty out all args, just in case this aborts, so cleanup
  388.      * can clean it up
  389.      */
  390.     msg->sm_NumArgs = argc;
  391.     for(i = 0; i < argc; i++) {
  392.         msg->sm_ArgList[i].wa_Lock = 0;
  393.         msg->sm_ArgList[i].wa_Name = 0;
  394.     }
  395.  
  396.     /* Get lock and name for wbargs */
  397.     for(i = 0; i < argc; i++) {
  398.         flock = Lock(argv[i]);
  399.         if(!flock) {
  400.             FreeStartup(msg);
  401.             return 0;
  402.         }
  403.         msg->sm_ArgList[i].wa_Lock = ParentDir(flock);
  404.         UnLock(flock);
  405.         if(!msg->sm_ArgList[i].wa_Lock) {
  406.             FreeStartup(msg);
  407.             return 0;
  408.         }
  409.  
  410.         /* Get the tail end of the file name. I could also do an Examine
  411.          * on the lock, but didn't want to bother allocating a File Info
  412.          * Block that wouldn't fit under the tracking via the startup
  413.          * message.
  414.          */
  415.         namep = argv[i];
  416.         for(s = argv[i]; *s; s++)
  417.             if(*s=='/' || *s==':')
  418.                 namep = s+1;
  419.         msg->sm_ArgList[i].wa_Name =
  420.             (char *)AllocMem(strlen(namep)+1, MEMF_PUBLIC);
  421.         if(!msg->sm_ArgList[i].wa_Name) {
  422.             FreeStartup(msg);
  423.             return 0;
  424.         }
  425.         strcpy(msg->sm_ArgList[i].wa_Name, namep);
  426.     }
  427.  
  428.     /* Create the process. It is now running, but will wait for the
  429.      * startup message.
  430.      */
  431.     msg->sm_Process =
  432.         CreateProc(msg->sm_ArgList[0].wa_Name, pri, msg->sm_Segment, stack);
  433.     if(!msg->sm_Process) {
  434.         FreeStartup(msg);
  435.         return 0;
  436.     }
  437.  
  438.     /* Initialise the message part of the startup message, and pass it to
  439.      * the process. At this point it will actually start ding work
  440.      */
  441.     msg->sm_Message.mn_ReplyPort = rport;
  442.     msg->sm_Message.mn_Length = sizeof(struct WBStartup);
  443.     msg->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  444.  
  445.     PutMsg(msg->sm_Process, msg);
  446.  
  447.     /* return message. Not very useful, but it's as meaningful a response as
  448.      * any.
  449.      */
  450.     return msg;
  451. }
  452. SHAR_EOF
  453. #    End of shell archive
  454. exit 0
  455. -- 
  456. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  457. Have five nice days.
  458.